﻿/*
 * Copyright 2013 Shaun McCloud
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
using System.Xml;
using Library;
using System.Threading;

namespace Astrid_Desktop
{
    public partial class frmMain : Form
    {
        private static Settings settings = new Settings();
        private static List<UrlParameter> urlParameters;
        private const string APP_ID = "EAAAAOZe4+KjX8fju/10SOmUzGOna0+vNXingwf5Gu3OGvkp";
        private const string APISECRET = "EAAAAHtBo18cC3U6jwH0Dbs96WL8/KiFgWJcDiXpAexo9Hso";
        private const string APIVERSION = "7";
        private const string BASEURL = "https://astrid.com/api/";
        private static string token = string.Empty;
        private static string tempXmlFile = Directory.GetCurrentDirectory() + "\\temp.xml";
        private static frmSplashScreen splashScreen = new frmSplashScreen();

        public frmMain()
        {
            InitializeComponent();
        }

        private void btnSettings_Click(object sender, EventArgs e)
        {
            frmSettings formSettings = new frmSettings();
            formSettings.ShowDialog();
            GetSettings();
        }

        private void frmMain_Resize(object sender, EventArgs e)
        {
            if (this.Width < 275)
            {
                this.Width = 275;
            }
            if (this.Height < 300)
            {
                this.Height = 300;
            }
            dgvTasks.Width = this.Width - 40;
            dgvTasks.Height = this.Height - 92;
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            DeleteTempFile();

            settings.Top = this.Top;
            while (settings.Top < 10)
            {
                settings.Top++;
            }

            settings.Left = this.Left;
            while (settings.Left < 10)
            {
                settings.Left++;
            }

            Serialization.SerializeAsXml(settings, "settings.xml");
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            frmSplashScreen.ShowSplashScreen();

            try
            {

                if (File.Exists(Directory.GetCurrentDirectory() + "\\" + "settings.xml"))
                {
                    GetSettings();
                }
                else
                {
                    settings.Username = Encryption.Encrypt("Username");
                    settings.Password = Encryption.Encrypt("Password");
                    Serialization.SerializeAsXml(settings, "settings.xml");
                    GetSettings();
                }

                while (settings.Left < 10)
                {
                    settings.Left++;
                }
                this.Left = settings.Left;

                while (settings.Top < 10)
                {
                    settings.Top++;
                }
                this.Top = settings.Top;

                if (string.IsNullOrEmpty(token))
                {
                    Login();
                }

                DeleteTempFile();

                if (string.IsNullOrEmpty(token))
                {
                    Login();
                }

                string json = ProcessRequest("task_list");

                PopulateDataGrid(json);
            }
            catch { }

            tmrSplash.Enabled = true;
        }

        /// <summary>
        /// Handle the user clicking the refresh button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRefresh_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(token))
            {
                Login();
            }

            string json = ProcessRequest("task_list");

            PopulateDataGrid(json);
        }

        private void DeleteTempFile()
        {
            if (File.Exists(tempXmlFile))
            {
                File.Delete(tempXmlFile);
            }
        }

        private void PopulateDataGrid(string json)
        {
            DeleteTempFile();

            XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(json, "tasks");

            StringWriter stringWriter = new StringWriter();
            XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter);

            doc.WriteTo(xmlTextWriter);

            using (StreamWriter sw = new StreamWriter(tempXmlFile))
            {
                sw.Write(stringWriter.ToString());
            }

            List<Task> tasks = new List<Task>();
            //Serialization.DeserializeFromXml(tempXmlFile, tasks);

            XmlReader xmlFile = XmlReader.Create(tempXmlFile, new XmlReaderSettings());

            dataSet.Clear();

            dataSet.ReadXml(xmlFile);

            this.dgvTasks.DataSource = dataSet.Tables["list"];

            xmlFile.Close();

            for (int i = 0; i < dgvTasks.Columns.Count; i++)
            {
                List<string> visibleColumns = new List<string>();
                visibleColumns.Add("title");
                visibleColumns.Add("importance");
                visibleColumns.Add("due");
                if (!visibleColumns.Contains(this.dgvTasks.Columns[i].Name.ToString()))
                {
                    this.dgvTasks.Columns[i].Visible = false;
                }
                else
                {
                    this.dgvTasks.Columns[i].Visible = true;
                }
            }
        }

        /// <summary>
        /// Login to Astrid
        /// </summary>
        private static void Login()
        {
            try
            {
                string json = ProcessRequest("user_signin");

                XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(json, "root");

                XmlNode tokenNode = doc.SelectSingleNode("/root/token");

                token = tokenNode.InnerText;
            }
            catch { }
        }

        private static UrlParameter InitParamter(string key, string value)
        {
            UrlParameter retVal = new UrlParameter();
            retVal.Key = key;
            retVal.Value = value;
            return retVal;
        }

        private static void GetSettings()
        {
            settings = Serialization.DeserializeFromXml<Settings>("settings.xml", settings);
        }

        /// <summary>
        /// Generic request processing
        /// </summary>
        /// <param name="requestName">Name of the request</param>
        /// <returns>The json from the request</returns>
        private static string ProcessRequest(string requestName)
        {
            //we will return this
            string retVal = string.Empty;

            GetSettings();

            urlParameters = new List<UrlParameter>();
            urlParameters.Add(InitParamter("secret", Encryption.Decrypt(settings.Password)));
            urlParameters.Add(InitParamter("app_id", Encryption.Decrypt(APP_ID)));
            urlParameters.Add(InitParamter("email", Encryption.Decrypt(settings.Username)));
            urlParameters.Add(InitParamter("provider", "password"));

            //get the time since epoch, no decimal
            var ts = DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1));
            var tmpTime = ts.TotalSeconds;
            tmpTime = Math.Round(tmpTime, 0, MidpointRounding.AwayFromZero);
            urlParameters.Add(InitParamter("time", tmpTime.ToString().Substring(0, tmpTime.ToString().Length)));

            //add some extra data to the strings based on the request type
            if (!string.IsNullOrEmpty(token))
            {
                urlParameters.Add(InitParamter("token", token));
            }

            //sort our parameters
            urlParameters.Sort();

            //set two strings to the request name, add a "?" to the first one
            string sigData = requestName + "?";
            string newSigData = requestName;

            //loop through each item in the list, append it to the strings we created above
            foreach (var item in urlParameters)
            {
                //do not add any extra characters to this one
                newSigData += item.Key + item.Value;

                //add "&" & "=" to this one
                if (sigData != requestName + "?")
                {
                    sigData += "&" + item.Key + "=" + item.Value;
                }
                else
                {
                    sigData += item.Key + "=" + item.Value;
                }
            }

            //append the api secret to the correct string
            newSigData += Encryption.Decrypt(APISECRET);

            //calculate our md5 signature based on the string w/o any extra characters
            string sig = Encryption.CalculateMD5Hash(newSigData);

            //build the full url
            string fullUrl = BASEURL + APIVERSION + "/" + sigData + "&sig=" + sig;

            //create a HttpWebRequest using the full url
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(fullUrl);
            request.Method = "POST";
            request.ContentType = "application/json; charset=utf-8";
            using (var response = (HttpWebResponse)request.GetResponse())
            {
                using (StreamReader sr = new StreamReader(response.GetResponseStream()))
                {
                    retVal = sr.ReadToEnd();
                }
            }
            return retVal;
        }

        private void tmrSplash_Tick(object sender, EventArgs e)
        {
            tmrSplash.Enabled = false;
            frmSplashScreen.CloseForm();
        }

        private void dgvTasks_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            DataGridViewRow item = new DataGridViewRow();
            item = this.dgvTasks.Rows[e.RowIndex];
            Task task = new Task();
            TaskDetail taskDetail = new TaskDetail(task);
        }
    }
}
